<template>
  <div class="vue-flow-demo">
    <h1>调用链追踪可视化</h1>
    <div class="demo-header">
      <el-input v-model="inputValue" placeholder="请输入内容" size="small" class="input-box" style="width: 320px; margin-right: 10px" />
      <el-button type="primary" size="small" @click="getList" :loading="loading" style="margin-right: 8px">查询</el-button>
      <el-button size="small" @click="getTrace('test1')" style="margin-right: 8px">操作1</el-button>
      <el-button size="small" @click="getTrace('test2')">操作2</el-button>
    </div>
    <div class="flow-container" v-for="(item, index) in mindNodes" :key="'flow-' + index">
      <VueFlow :nodes="item.nodes" :edges="item.edges" class="vue-flow" fit-view-on-init @nodes-initialized="layoutGraph(item, 'LR')" @node-click="onNodeClick">
        <Background />
        <Controls />
        <MiniMap />
      </VueFlow>
      <!-- 节点详情面板 -->
      <div v-if="selectedNode" class="node-details-panel" :style="selectedNode.panelPosition">
        <el-card size="mini" class="node-details-card" :body-style="{ padding: '0' }" shadow="always">
          <!-- 卡片头部 -->
          <template #header>
            <div class="card-header">
              <div class="header-left">
                <el-icon class="header-icon">
                  <InfoFilled />
                </el-icon>
                <span class="header-title">节点详情</span>
              </div>
              <div class="header-right">
                <el-button type="text" :icon="isPanelCollapsed ? 'ArrowDown' : 'ArrowUp'" @click="togglePanelCollapse" class="collapse-button" circle :title="isPanelCollapsed ? '展开面板' : '折叠面板'" />
                <el-button type="text" icon="Close" @click="closeDetails" class="close-button" circle />
              </div>
            </div>
          </template>

          <!-- 卡片内容 -->
          <div class="card-content" :class="{ collapsed: isPanelCollapsed }">
            <!-- 折叠状态下的简化信息 -->
            <div v-if="isPanelCollapsed" class="collapsed-content">
              <div class="collapsed-item">
                <el-text type="primary" class="collapsed-method">
                  {{ selectedNode.data.title }}
                </el-text>
              </div>
              <div class="collapsed-item">
                <el-tag :type="
                    getCostTimeType(selectedNode.data.costTime, selectedNode.data.warnThreshold)
                  " effect="light" size="small">
                  <el-icon>
                    <Timer />
                  </el-icon>
                  {{ selectedNode.data.costTime }}ms
                </el-tag>
                <el-tag :type="getStatusType(selectedNode.data.status)" effect="dark" size="small" class="status-tag-collapsed">
                  <el-icon v-if="selectedNode.data.status === 'SUCCESS'">
                    <CircleCheckFilled />
                  </el-icon>
                  <el-icon v-else-if="selectedNode.data.status === 'FAIL'">
                    <CircleCloseFilled />
                  </el-icon>
                  <el-icon v-else>
                    <WarningFilled />
                  </el-icon>
                  {{ selectedNode.data.status }}
                </el-tag>
              </div>
            </div>

            <!-- 展开状态下的完整信息 -->
            <div v-else>
              <!-- 基本信息 -->
              <el-descriptions :column="1" border size="small" class="node-descriptions">
                <el-descriptions-item label="方法全名">
                  <el-text type="primary" class="method-path">
                    {{ selectedNode.data.title }}
                  </el-text>
                </el-descriptions-item>

                <el-descriptions-item label="执行耗时">
                  <el-tag :type="
                      getCostTimeType(selectedNode.data.costTime, selectedNode.data.warnThreshold)
                    " effect="light" class="cost-time-tag">
                    <el-icon>
                      <Timer />
                    </el-icon>
                    {{ selectedNode.data.costTime }}ms
                  </el-tag>
                </el-descriptions-item>

                <el-descriptions-item label="执行状态">
                  <el-tag :type="getStatusType(selectedNode.data.status)" effect="dark" class="status-tag">
                    <el-icon v-if="selectedNode.data.status === 'SUCCESS'">
                      <CircleCheckFilled />
                    </el-icon>
                    <el-icon v-else-if="selectedNode.data.status === 'FAIL'">
                      <CircleCloseFilled />
                    </el-icon>
                    <el-icon v-else>
                      <WarningFilled />
                    </el-icon>
                    {{ selectedNode.data.status }}
                  </el-tag>
                </el-descriptions-item>

                <el-descriptions-item label="警告阈值">
                  <el-text type="info"> {{ selectedNode.data.warnThreshold }}ms </el-text>
                </el-descriptions-item>
              </el-descriptions>

              <!-- 参数信息折叠面板 -->
              <el-collapse v-model="activeCollapse" class="params-collapse" accordion>
                <el-collapse-item v-if="selectedNode.data.exceptionStack" name="exception" class="param-item">
                  <template #title>
                    <div class="collapse-title">
                      <el-icon size="medium">
                        <CircleCloseFilled style="color: #ef4444;" />
                      </el-icon>
                      <span style="color: #ef4444;">错误信息</span>
                      <el-button type="text" size="small" :icon="CopyDocument" @click.stop="copyToClipboard(selectedNode.data.exceptionStack)" class="copy-button">
                        复制
                      </el-button>
                    </div>
                  </template>
                  <div class="param-content">
                    <el-scrollbar height="200px" class="param-scrollbar">
                      <div class="json-content">
                        <pre class="json-formatted">{{ selectedNode.data.exceptionStack }}</pre>
                      </div>
                    </el-scrollbar>
                  </div>
                </el-collapse-item>

                <el-collapse-item title="请求参数" name="request" class="param-item">
                  <template #title>
                    <div class="collapse-title">
                      <el-icon>
                        <Document />
                      </el-icon>
                      <span>请求参数</span>
                      <el-button type="text" size="small" :icon="CopyDocument" @click.stop="copyToClipboard(formatJson(selectedNode.data.requestParam))" class="copy-button">
                        复制
                      </el-button>
                    </div>
                  </template>
                  <div class="param-content">
                    <el-scrollbar height="200px" class="param-scrollbar">
                      <div class="json-content">
                        <pre class="json-formatted">{{ formattedRequestParam }}</pre>
                      </div>
                    </el-scrollbar>
                  </div>
                </el-collapse-item>

                <el-collapse-item title="响应参数" name="response" class="param-item">
                  <template #title>
                    <div class="collapse-title">
                      <el-icon>
                        <DocumentCopy />
                      </el-icon>
                      <span>响应参数</span>
                      <el-button type="text" size="small" :icon="CopyDocument" @click.stop="copyToClipboard(formatJson(selectedNode.data.responseParam))" class="copy-button">
                        复制
                      </el-button>
                    </div>
                  </template>
                  <div class="param-content">
                    <el-scrollbar height="200px" class="param-scrollbar">
                      <div class="json-content">
                        <pre class="json-formatted">{{ formattedResponseParam }}</pre>
                      </div>
                    </el-scrollbar>
                  </div>
                </el-collapse-item>
              </el-collapse>
            </div>
          </div>
        </el-card>
      </div>
    </div>

    <div v-if="mindNodes.length" class="demo-info">
      <!-- 功能说明 -->
      <div class="feature-section">
        <h3>
          <el-icon class="section-icon">
            <InfoFilled />
          </el-icon>
          功能说明
        </h3>
        <div class="feature-grid">
          <div class="feature-card">
            <div class="feature-header">
              <el-icon class="feature-icon">
                <Search />
              </el-icon>
              <h4>调用链查询</h4>
            </div>
            <p>通过输入TraceId查询完整的调用链数据，支持实时查询和模拟数据生成</p>
          </div>

          <div class="feature-card">
            <div class="feature-header">
              <el-icon class="feature-icon">
                <Share />
              </el-icon>
              <h4>调用链可视化</h4>
            </div>
            <p>以流程图形式展示完整的调用链路，清晰显示方法间的调用关系</p>
          </div>

          <div class="feature-card">
            <div class="feature-header">
              <el-icon class="feature-icon">
                <Timer />
              </el-icon>
              <h4>性能监控</h4>
            </div>
            <p>实时显示每个方法的执行耗时，边上标注具体时间，支持性能阈值警告</p>
          </div>

          <div class="feature-card">
            <div class="feature-header">
              <el-icon class="feature-icon">
                <View />
              </el-icon>
              <h4>详情查看</h4>
            </div>
            <p>点击节点查看详细信息，包括方法全名、执行状态、请求响应参数、异常堆栈等</p>
          </div>

          <div class="feature-card">
            <div class="feature-header">
              <el-icon class="feature-icon">
                <DocumentCopy />
              </el-icon>
              <h4>数据复制</h4>
            </div>
            <p>支持一键复制请求参数、响应参数和异常信息到剪贴板</p>
          </div>

          <div class="feature-card">
            <div class="feature-header">
              <el-icon class="feature-icon">
                <ZoomIn />
              </el-icon>
              <h4>交互控制</h4>
            </div>
            <p>支持缩放、拖拽、小地图导航等交互操作，提供最佳的可视化体验</p>
          </div>
        </div>
      </div>

      <!-- 颜色编码说明 -->
      <div class="color-section">
        <h3>
          <el-icon class="section-icon">
            <Palette />
          </el-icon>
          颜色编码规则
        </h3>
        <div class="color-grid">
          <div class="color-card">
            <div class="color-header">
              <div class="color-indicator fail"></div>
              <h4>失败状态</h4>
            </div>
            <p>方法执行失败时显示红色，连接线带有红色动画效果</p>
          </div>

          <div class="color-card">
            <div class="color-header">
              <div class="color-indicator warning"></div>
              <h4>超时警告</h4>
            </div>
            <p>执行时间超过警告阈值时显示橙色</p>
          </div>

          <div class="color-card">
            <div class="color-header">
              <div class="color-indicator fast"></div>
              <h4>快速执行</h4>
            </div>
            <p>执行时间小于100ms时显示绿色</p>
          </div>

          <div class="color-card">
            <div class="color-header">
              <div class="color-indicator medium"></div>
              <h4>中等执行</h4>
            </div>
            <p>执行时间100-300ms时显示紫色</p>
          </div>

          <div class="color-card">
            <div class="color-header">
              <div class="color-indicator slow"></div>
              <h4>较慢执行</h4>
            </div>
            <p>执行时间超过300ms时显示青色</p>
          </div>
        </div>
      </div>

      <!-- 状态说明 -->
      <div class="status-section">
        <h3>
          <el-icon class="section-icon">
            <CircleCheckFilled />
          </el-icon>
          状态说明
        </h3>
        <div class="status-grid">
          <div class="status-item">
            <el-tag type="success" effect="dark" size="large">
              <el-icon>
                <CircleCheckFilled />
              </el-icon>
              SUCCESS
            </el-tag>
            <span>方法执行成功</span>
          </div>
          <div class="status-item">
            <el-tag type="danger" effect="dark" size="large">
              <el-icon>
                <CircleCloseFilled />
              </el-icon>
              FAIL
            </el-tag>
            <span>方法执行失败</span>
          </div>
          <div class="status-item">
            <el-tag type="warning" effect="dark" size="large">
              <el-icon>
                <WarningFilled />
              </el-icon>
              WARNING
            </el-tag>
            <span>方法执行异常或超时</span>
          </div>
        </div>
      </div>

      <!-- 交互说明 -->
      <div class="interaction-section">
        <h3>
          <el-icon class="section-icon">
            <Mouse />
          </el-icon>
          交互操作
        </h3>
        <div class="interaction-list">
          <div class="interaction-item">
            <el-icon class="interaction-icon">
              <Mouse />
            </el-icon>
            <div class="interaction-content">
              <strong>点击节点：</strong>查看节点详细信息，包括方法全名、执行耗时、状态、请求响应参数等
            </div>
          </div>
          <div class="interaction-item">
            <el-icon class="interaction-icon">
              <ArrowUp />
            </el-icon>
            <div class="interaction-content">
              <strong>折叠/展开面板：</strong>点击面板右上角的箭头按钮切换详情面板的折叠状态
            </div>
          </div>
          <div class="interaction-item">
            <el-icon class="interaction-icon">
              <DocumentCopy />
            </el-icon>
            <div class="interaction-content">
              <strong>复制数据：</strong>点击参数面板中的"复制"按钮，一键复制请求参数、响应参数或异常信息
            </div>
          </div>
          <div class="interaction-item">
            <el-icon class="interaction-icon">
              <ZoomIn />
            </el-icon>
            <div class="interaction-content">
              <strong>缩放控制：</strong>使用右下角的控制按钮进行缩放操作，支持适应画布和重置视图
            </div>
          </div>
          <div class="interaction-item">
            <el-icon class="interaction-icon">
              <Location />
            </el-icon>
            <div class="interaction-content">
              <strong>小地图导航：</strong>左下角的小地图显示整个调用链的缩略图，点击可快速定位
            </div>
          </div>
        </div>
      </div>

      <!-- 数据说明 -->
      <div class="data-section">
        <h3>
          <el-icon class="section-icon">
            <Document />
          </el-icon>
          数据说明
        </h3>
        <div class="data-content">
          <p><strong>数据来源：</strong>通过TraceId查询后端接口获取调用链数据</p>
          <p><strong>数据结构：</strong>支持嵌套的调用链结构，每个节点包含方法信息、执行时间、状态、参数等</p>
          <p><strong>查询方式：</strong>输入TraceId后点击"查询"按钮，或使用"操作1"/"操作2"按钮生成模拟数据</p>
          <p><strong>实时更新：</strong>支持实时查询最新的调用链数据</p>
        </div>
      </div>
    </div>
    <div v-else style="font-size: 12px; color: lightgray">
      {{ loading ? '可视化节点生成中...' : '暂无数据' }}
    </div>
  </div>
</template>

<script>
import { Background } from '@vue-flow/background'
import { Controls } from '@vue-flow/controls'
import { VueFlow, useVueFlow } from '@vue-flow/core'
import { MiniMap } from '@vue-flow/minimap'
import { ElMessage } from 'element-plus'
import { ref, nextTick } from 'vue'

// 导入API工具
import { get, getWithParams } from '@/utils/api.js'
// 导入数据解析工具
import { parseTraceData } from '@/utils/data.js'
import { useLayout } from '@/utils/useLayout'

export default {
  name: 'VueFlowDemo',
  components: {
    VueFlow,
    Background,
    Controls,
    MiniMap
  },
  setup () {
    const mindNodes = ref([])
    const selectedNode = ref(null)
    const activeCollapse = ref('')
    const loading = ref(false)
    const formattedRequestParam = ref('')
    const formattedResponseParam = ref('')
    const isPanelCollapsed = ref(false)
    const inputValue = ref('3fefab77a4054740b14ed59007543d0a')
    const { layout } = useLayout()
    const { fitView } = useVueFlow()

    // 节点点击事件处理
    const onNodeClick = event => {
      const node = event.node

      // 格式化参数数据
      formattedRequestParam.value = formatJson(node.data.requestParam)
      formattedResponseParam.value = formatJson(node.data.responseParam)

      // 设置面板为固定位置（右上角）
      selectedNode.value = {
        ...node,
        panelPosition: {
          right: '20px',
          top: '20px'
        }
      }
    }

    // 关闭详情面板
    const closeDetails = () => {
      selectedNode.value = null
      isPanelCollapsed.value = false // 重置折叠状态
    }

    // 切换面板折叠状态
    const togglePanelCollapse = () => {
      isPanelCollapsed.value = !isPanelCollapsed.value
    }

    // 获取状态样式类
    const getStatusClass = status => {
      return {
        'status-success': status === 'SUCCESS',
        'status-error': status === 'FAIL',
        'status-warning': status === 'WARNING'
      }
    }

    // 获取状态类型（用于Element Plus标签）
    const getStatusType = status => {
      switch (status) {
        case 'SUCCESS':
          return 'success'
        case 'FAIL':
          return 'danger'
        case 'WARNING':
          return 'warning'
        default:
          return 'info'
      }
    }

    // 获取耗时类型（用于Element Plus标签）
    const getCostTimeType = (costTime, warnThreshold) => {
      if (costTime > warnThreshold) {
        return 'danger'
      } else if (costTime > warnThreshold * 0.8) {
        return 'warning'
      } else {
        return 'success'
      }
    }

    // 复制到剪贴板
    const copyToClipboard = async text => {
      try {
        await navigator.clipboard.writeText(text)
        ElMessage.success('复制成功')
      } catch (err) {
        console.error('复制失败:', err)
        ElMessage.error('复制失败')
      }
    }

    // 格式化JSON数据
    const formatJson = data => {
      if (data === null || data === undefined) return '无'
      try {
        return JSON.stringify(data, null, 2)
      } catch (error) {
        return String(data)
      }
    }

    // 高亮JSON字符串
    const highlightJson = jsonString => {
      if (jsonString === '无') return jsonString

      return jsonString
        .replace(/(".*?")\s*:/g, '<span class="json-key">$1</span>:')
        .replace(/:\s*(".*?")/g, ': <span class="json-string">$1</span>')
        .replace(/:\s*(\d+)/g, ': <span class="json-number">$1</span>')
        .replace(/:\s*(true|false|null)/g, ': <span class="json-boolean">$1</span>')
    }

    async function layoutGraph (item, direction) {
      item.nodes = layout(item.nodes, item.edges, direction)

      nextTick(() => {
        fitView()
      })
    }

    // 查询接口调用
    const getList = async () => {
      try {
        const traceId = inputValue.value
        const url = '/visual-link-tracking/trace/search'
        selectedNode.value = null
        const params = { traceId }
        // 清空之前的mindNodes数据
        mindNodes.value = []
        loading.value = true
        const response = await getWithParams(url, params)

        // 处理响应数据
        if (response && response.data && response.data.traceNodes) {
          console.log('查询结果:', response)
          // 遍历traceNodes数组，调用parseTraceData处理每个节点
          response.data.traceNodes.forEach(traceNode => {
            try {
              const data = parseTraceData(traceNode)
              mindNodes.value.push(data)
            } catch (parseError) {
              console.error('解析节点数据失败:', parseError, traceNode)
            }
          })
          ElMessage.success(`查询成功，共加载 ${mindNodes.value.length} 个根节点`)
        } else {
          ElMessage.warning('未找到相关数据')
        }
      } catch (error) {
        console.error('查询失败:', error)
        ElMessage.error('查询失败: ' + error.message)
      }
      loading.value = false
    }

    // 查询接口调用
    const getTrace = async test1 => {
      try {
        const url = '/visual-link-tracking/demo/' + test1
        const response = await get(url)
        // 处理响应数据
        if (response && response.data) {
          const messge = '模拟获取traceId：' + response.data.traceId
          console.log(messge)
          ElMessage.info(messge)
          inputValue.value = response.data.traceId
          mindNodes.value = []
        } else {
          ElMessage.warning('未找到相关数据')
        }
      } catch (error) {
        console.error('查询失败:', error)
        ElMessage.error('查询失败: ' + error.message)
      }
    }

    return {
      loading,
      mindNodes,
      selectedNode,
      activeCollapse,
      formattedRequestParam,
      formattedResponseParam,
      isPanelCollapsed,
      inputValue,
      onNodeClick,
      closeDetails,
      togglePanelCollapse,
      getStatusClass,
      getStatusType,
      getCostTimeType,
      copyToClipboard,
      formatJson,
      highlightJson,
      layoutGraph,
      getList,
      getTrace
    }
  }
}
</script>

<style scoped>
.vue-flow-demo {
  min-height: 100vh;
  padding: 20px;
  background-color: #f8fafc;
}

.demo-header {
  text-align: center;
  margin-bottom: 30px;
  display: flex;
}

.demo-header h1 {
  color: #1e293b;
  font-size: 2.5rem;
  margin-bottom: 10px;
}

.demo-header p {
  color: #64748b;
  font-size: 1.1rem;
  max-width: 600px;
  margin: 0 auto;
}

.flow-container {
  width: 100%;
  height: 600px;
  border: 2px solid #e2e8f0;
  border-radius: 12px;
  overflow: hidden;
  background-color: #ffffff;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
  margin: 20px 0;
}

.vue-flow {
  width: 100%;
  height: 100%;
}

.demo-info {
  margin-top: 30px;
  max-width: 1200px;
  margin-left: auto;
  margin-right: auto;
  padding: 0 20px;
}

.demo-info h3 {
  color: #1e293b;
  margin-bottom: 20px;
  font-size: 1.4rem;
  display: flex;
  align-items: center;
  gap: 8px;
}

.section-icon {
  color: #409eff;
  font-size: 20px;
}

/* 功能说明样式 */
.feature-section {
  margin-bottom: 40px;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
  margin-top: 20px;
}

.feature-card {
  background-color: #ffffff;
  padding: 20px;
  border-radius: 12px;
  border: 1px solid #e2e8f0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.feature-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.feature-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.feature-icon {
  color: #409eff;
  font-size: 24px;
}

.feature-card h4 {
  color: #1e293b;
  font-size: 1.1rem;
  margin: 0;
  font-weight: 600;
}

.feature-card p {
  color: #64748b;
  line-height: 1.6;
  margin: 0;
  font-size: 0.95rem;
}

/* 颜色编码说明样式 */
.color-section {
  margin-bottom: 40px;
}

.color-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 16px;
  margin-top: 20px;
}

.color-card {
  background-color: #ffffff;
  padding: 16px;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.color-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
}

.color-indicator {
  width: 20px;
  height: 20px;
  border-radius: 4px;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px #e2e8f0;
}

.color-indicator.fail {
  background-color: #ef4444;
}

.color-indicator.warning {
  background-color: #f59e0b;
}

.color-indicator.fast {
  background-color: #10b981;
}

.color-indicator.medium {
  background-color: #8b5cf6;
}

.color-indicator.slow {
  background-color: #06b6d4;
}

.color-card h4 {
  color: #1e293b;
  font-size: 1rem;
  margin: 0;
  font-weight: 600;
}

.color-card p {
  color: #64748b;
  font-size: 0.9rem;
  line-height: 1.5;
  margin: 0;
}

/* 状态说明样式 */
.status-section {
  margin-bottom: 40px;
}

.status-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin-top: 20px;
}

.status-item {
  display: flex;
  align-items: center;
  gap: 12px;
  background-color: #ffffff;
  padding: 16px 20px;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.status-item span {
  color: #64748b;
  font-size: 0.95rem;
}

/* 交互说明样式 */
.interaction-section {
  margin-bottom: 40px;
}

.interaction-list {
  background-color: #ffffff;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  margin-top: 20px;
}

.interaction-item {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 16px;
  padding: 12px;
  border-radius: 6px;
  transition: background-color 0.2s ease;
}

.interaction-item:hover {
  background-color: #f8fafc;
}

.interaction-item:last-child {
  margin-bottom: 0;
}

.interaction-icon {
  color: #409eff;
  font-size: 20px;
  margin-top: 2px;
}

.interaction-content {
  flex: 1;
  color: #475569;
  line-height: 1.6;
}

.interaction-content strong {
  color: #1e293b;
}

/* 数据说明样式 */
.data-section {
  margin-bottom: 40px;
}

.data-content {
  background-color: #ffffff;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  margin-top: 20px;
}

.data-content p {
  margin-bottom: 12px;
  color: #475569;
  line-height: 1.6;
}

.data-content p:last-child {
  margin-bottom: 0;
}

.data-content strong {
  color: #1e293b;
}

.back-link {
  text-align: center;
  margin-top: 30px;
}

.nav-button {
  display: inline-block;
  padding: 12px 24px;
  background-color: #3b82f6;
  color: white;
  text-decoration: none;
  border-radius: 6px;
  font-weight: 500;
  transition: background-color 0.3s;
}

.nav-button:hover {
  background-color: #2563eb;
}

/* 节点详情面板样式 */
.node-details-panel {
  width: 450px;
  max-width: 90vw;
  max-height: 80vh;
  overflow: hidden;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  position: relative;
}

.header-left {
  display: flex;
  align-items: center;
  gap: 8px;
}

.header-right {
  display: flex;
  align-items: center;
}

.header-icon {
  color: #409eff;
  font-size: 18px;
}

.header-title {
  font-weight: 600;
  color: #303133;
  font-size: 16px;
}

.collapse-button {
  color: #909399;
  font-size: 16px;
}

.collapse-button:hover {
  color: #409eff;
}

.close-button {
  color: #909399;
  font-size: 18px;
}

.close-button:hover {
  color: #409eff;
}

/* 固定位置面板样式 */
.node-details-panel {
  position: fixed;
  z-index: 1000;
}

.card-content {
  padding: 16px;
  max-height: 60vh;
  overflow-y: auto;
  transition: all 0.3s ease;
}

.card-content.collapsed {
  padding: 12px;
  max-height: 120px;
}

.collapsed-content {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.collapsed-item {
  display: flex;
  align-items: center;
  gap: 8px;
}

.collapsed-method {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 11px;
  word-break: break-all;
  line-height: 1.3;
  max-width: 400px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.status-tag-collapsed {
  margin-left: 8px;
}

.node-descriptions {
  margin-bottom: 16px;
}

.method-path {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 12px;
  word-break: break-all;
}

.cost-time-tag {
  font-weight: 600;
}

.status-tag {
  font-weight: 600;
}

.params-collapse {
  margin-top: 16px;
}

.param-item {
  margin-bottom: 8px;
}

.collapse-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0 4px;
}

.collapse-title .el-icon {
  margin-right: 8px;
  color: #409eff;
}

.collapse-title span {
  flex: 1;
  font-weight: 500;
}

.copy-button {
  margin-left: auto;
  padding: 4px 8px;
  font-size: 12px;
}

.param-content {
  padding: 12px;
}

.param-scrollbar {
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  background-color: #f8f9fa;
}

.json-content {
  padding: 12px;
}

.json-formatted {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
  font-size: 12px;
  line-height: 1.5;
  margin: 0;
  white-space: pre-wrap;
  word-wrap: break-word;
  color: #2c3e50;
  background: transparent;
}

/* JSON语法高亮样式 */
.json-key {
  color: #e74c3c;
  font-weight: 600;
}

.json-string {
  color: #27ae60;
}

.json-number {
  color: #3498db;
  font-weight: 600;
}

.json-boolean {
  color: #9b59b6;
  font-weight: 600;
}

.json-formatted {
  color: #2c3e50;
}

/* 改进的JSON显示样式 */
.json-formatted {
  background: linear-gradient(90deg, #f8f9fa 0%, #ffffff 100%);
  border-left: 3px solid #409eff;
  padding-left: 8px;
}

/* 状态样式 */
.status-success {
  color: #10b981;
  font-weight: 600;
}

.status-error {
  color: #ef4444;
  font-weight: 600;
}

.status-warning {
  color: #f59e0b;
  font-weight: 600;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .vue-flow-demo {
    padding: 10px;
  }

  .demo-header h1 {
    font-size: 2rem;
  }

  .flow-container {
    height: 400px;
  }

  .node-details-panel {
    position: fixed !important;
    top: 10px !important;
    left: 10px !important;
    right: 10px !important;
    width: auto !important;
    max-width: calc(100vw - 20px) !important;
    max-height: 70vh;
    transform: none !important;
  }

  .node-details-card {
    height: auto !important;
  }

  .card-content {
    max-height: 50vh;
  }

  .collapse-title {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }

  .copy-button {
    margin-left: 0;
    align-self: flex-end;
  }

  /* 使用说明响应式 */
  .demo-info {
    padding: 0 10px;
  }

  .feature-grid {
    grid-template-columns: 1fr;
    gap: 16px;
  }

  .color-grid {
    grid-template-columns: 1fr;
    gap: 12px;
  }

  .status-grid {
    flex-direction: column;
    gap: 12px;
  }

  .status-item {
    padding: 12px 16px;
  }

  .interaction-item {
    flex-direction: column;
    gap: 8px;
    padding: 8px;
  }

  .interaction-icon {
    align-self: flex-start;
  }
}
</style>
